Fix application startup failure with springdoc.show-actuator=true and a separate management port - #590
Open
clun wants to merge 1 commit into
Open
Fix application startup failure with springdoc.show-actuator=true and a separate management port#590clun wants to merge 1 commit into
clun wants to merge 1 commit into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #590 +/- ##
============================================
+ Coverage 87.69% 95.71% +8.02%
- Complexity 188 246 +58
============================================
Files 51 51
Lines 520 514 -6
Branches 21 20 -1
============================================
+ Hits 456 492 +36
+ Misses 53 12 -41
+ Partials 11 10 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Applications using the FF4J Spring Boot starter fail to start when springdoc's actuator
support is enabled with a management port different from the server port:
Startup fails with:
This was originally reported against
ff4j-spring-boot-autoconfigure1.9 (Spring Boot 2.6 /springdoc 1.6) and is still reproducible on current
mainwith Spring Boot 4.1.0 andspringdoc 3.0.3.
Root cause
When
springdoc.show-actuator=trueand the management port differs from the server port,springdoc registers
springdocBeanFactoryPostProcessor3, aBeanFactoryPostProcessorwhoseconstructor depends on
List<GroupedOpenApi>. Resolving that list forces Spring to instantiateFF4JOpenApiConfiguration(the factory of FF4J'sGroupedOpenApibean) during thebean-factory-post-processing phase — before any
BeanPostProcessoris registered.At that point in the container lifecycle:
AutowiredAnnotationBeanPostProcessoris not registered yet, so Spring cannot resolve theparameterized constructor of
FF4JOpenApiConfigurationand falls back to a defaultconstructor, which does not exist →
NoSuchMethodException.ConfigurationPropertiesBindingPostProcessoris notregistered either, so any
@ConfigurationPropertiesbean created this early would remainunbound forever — user settings like
ff4j.api.spring-doc.groupandff4j.api.context-pathwould be silently ignored (the singleton is created once and neverpost-processed).
Fix
FF4JOpenApiConfigurationno longer uses constructor injection, so it is safe to instantiate atany lifecycle phase:
GroupedOpenApibean method resolves FF4J settings by binding them directly from theEnvironmentviaBinder.get(environment).bindOrCreate("ff4j", ...)instead of injecting theFF4JConfigurationPropertiesbean. TheEnvironmentis registered as a resolvable dependencybefore bean-factory post-processing, so this works during early instantiation and honors the
user's configured values (addressing point 2 above).
initblock (excluding FF4J paths from the OpenAPIdocumentation when
ff4j.api.spring-doc.enabledis false) is moved to a dedicatedInitializingBeanthat runs in the normal bean lifecycle, guarded by@ConditionalOnProperty(..., havingValue = "false", matchIfMissing = true)— same semanticsas before.
SpringDocConfigPropertiesis consumed through anObjectProvider, preserving theprevious lenient behavior in contexts where springdoc is on the classpath but inactive
(e.g. non-web applications).
Testing
FF4JOpenApiActuatorConfigurationTestreproduces the reported setup(
springdoc.show-actuator=true,management.server.portdifferent fromserver.port,ff4j.api.spring-doc.enabled=true). It failed with the reportedNo default constructor founderror before the fix and passes after. It also asserts that a custom
ff4j.api.spring-doc.groupvalue is correctly bound during early instantiation, guardingagainst the silent-unbound-properties regression.
spring-boot-starter-actuatorandspring-boot-starter-webwere added toff4j-spring-boot-autoconfigure-commonin test scope only to support the regression test.Changed files
ff4j-spring-boot-autoconfigure-common/src/main/kotlin/.../FF4JOpenApiConfiguration.ktBinder-based property resolution, exclusion logic moved toInitializingBeanff4j-spring-boot-autoconfigure-common/src/test/kotlin/.../FF4JOpenApiActuatorConfigurationTest.ktff4j-spring-boot-autoconfigure-common/pom.xmlspring-boot-starter-actuatorandspring-boot-starter-webFixes bug 736 in ff4j core repo